package basedeal

import (
	"core/datetime"
	"core/redis"
	"fmt"
	"iotall/iotcore/entity"
	"strconv"

	"github.com/todocoder/go-stream/stream"
)

const (
	DevicePrefix = "Device:"
)

func RedisSaveDevice(m *entity.StdPkg) (*[]entity.StdPkgDeviceMongo, error) {
	var r = make([]entity.StdPkgDeviceMongo, 0)
	for _, v := range m.Devices {
		var key = DevicePrefix + GetDId(m.Sid, v.Id)
		var mdvs = &entity.StdPkgDeviceMongo{}
		err := redis.RedisGetStruct(key, mdvs)

		if mdvs.Id == "" {
			mdvs, err = GetInsertDevice(m.Sid, &v)
			if err != nil {
				return nil, err
			}
		} else {
			GetUpdateDevice(&v, mdvs)
		}
		r = append(r, *mdvs)

	}
	return &r, nil
}

func GetInsertDevice(sid string, m *entity.StdPkgDevice) (*entity.StdPkgDeviceMongo, error) {
	var mdev = &entity.StdPkgDeviceMongo{
		Id:          fmt.Sprintf("%v*%v", sid, m.Id),
		Sid:         sid,
		Did:         m.Id,
		Name:        m.Name,
		Ability:     m.Ability,
		Props:       make([]entity.PropDefine, 0),
		CrtDt:       datetime.NowStr(),
		PropCustoms: make([]entity.PropCustom, 0),
		PropValues:  make([]entity.PropValue, 0),
	}
	var sm = stream.Of(m.Props...).Sorted(func(a, b entity.StdPkgProp) bool {
		return a.Id < b.Id
	})
	sm.ForEach(func(item entity.StdPkgProp) {
		var mprop = &entity.PropDefine{
			Id:      item.Id,
			Name:    item.Name,
			Type:    item.Type,
			Vl:      item.Vl,
			Vll:     item.Vll,
			Vh:      item.Vh,
			Vhh:     item.Vhh,
			Scope:   "",
			Unit:    item.Unit,
			Monitor: item.Monitor,
		}
		if item.Vl != "" || item.Vh != "" {
			mprop.Scope = fmt.Sprintf("%v~%v", item.Vl, item.Vh)
		}
		mdev.Props = append(mdev.Props, *mprop)

		var mpropvalue = &entity.PropValue{
			Id:    item.Id,
			Fv:    item.Fv,
			Sv:    item.Sv,
			State: item.State,
			CrtDt: datetime.NowStr(),
		}
		if mpropvalue.Sv == "" {
			mpropvalue.Sv = strconv.FormatFloat(float64(mpropvalue.Fv), 'f', -1, 32)
		}
		mdev.PropValues = append(mdev.PropValues, *mpropvalue)
	})
	return mdev, nil
}

func GetUpdateDevice(m *entity.StdPkgDevice, mdev *entity.StdPkgDeviceMongo) error {
	var bNeedSave = false
	for index, _ := range m.Props {
		var item = m.Props[index]
		var mprop = &entity.PropDefine{
			Id:      item.Id,
			Name:    item.Name,
			Type:    item.Type,
			Vl:      item.Vl,
			Vll:     item.Vll,
			Vh:      item.Vh,
			Vhh:     item.Vhh,
			Scope:   "",
			Unit:    item.Unit,
			Monitor: item.Monitor,
		}
		if item.Vl != "" || item.Vh != "" {
			mprop.Scope = fmt.Sprintf("%v~%v", item.Vl, item.Vh)
		}
		var moldprop = GetOldProp(&mdev.Props, mprop.Id)
		if moldprop == nil {
			mdev.Props = append(mdev.Props, *mprop)
			bNeedSave = true
		} else if mprop.Type != moldprop.Type ||
			mprop.Vl != moldprop.Vl ||
			mprop.Vll != moldprop.Vll ||
			mprop.Vh != moldprop.Vh ||
			mprop.Vhh != moldprop.Vhh ||
			mprop.Unit != moldprop.Unit ||
			mprop.Monitor != moldprop.Monitor {
			mprop.Type = moldprop.Type
			moldprop.Vl = mprop.Vl
			moldprop.Vll = mprop.Vll
			moldprop.Vh = mprop.Vh
			moldprop.Vhh = mprop.Vhh
			moldprop.Unit = mprop.Unit
			moldprop.Monitor = mprop.Monitor
			bNeedSave = true
		}

		var moldvalue = GetOldValue(&mdev.PropValues, mprop.Id)
		if moldvalue == nil {
			var mpropvalue = &entity.PropValue{
				Id:    item.Id,
				Fv:    item.Fv,
				Sv:    item.Sv,
				State: item.State,
				CrtDt: datetime.NowStr(),
			}
			if mpropvalue.Sv == "" {
				mpropvalue.Sv = strconv.FormatFloat(float64(mpropvalue.Fv), 'f', -1, 32)
			}
			mdev.PropValues = append(mdev.PropValues, *mpropvalue)

			bNeedSave = true
		} else {

			moldvalue.Fv = item.Fv
			moldvalue.Sv = item.Sv
			moldvalue.State = item.State
			moldvalue.CrtDt = item.CrtDt
			if moldvalue.Sv == "" {
				moldvalue.Sv = strconv.FormatFloat(float64(moldvalue.Fv), 'f', -1, 32)
			}
		}
	}

	if bNeedSave {
		var sm2 = stream.Of(mdev.Props...).Sorted(func(a, b entity.PropDefine) bool {
			return a.Id < b.Id
		})
		var defines []entity.PropDefine
		sm2.ForEach(func(item entity.PropDefine) {
			defines = append(defines, item)
		})
		mdev.Props = defines
	}
	return nil
}
